home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Database / AddressBook / Source / Controller.m < prev    next >
Text File  |  1992-08-24  |  7KB  |  267 lines

  1. /* Controller.m:
  2.  * You may freely copy, distribute, and reuse the code in this example.
  3.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  4.  * fitness for any particular use.
  5.  *
  6.  * Written by: Mai Nguyen, NeXT Developer Support
  7.  *
  8.  *
  9.  */
  10.  
  11. #import <appkit/appkit.h>
  12. #import <dbkit/dbkit.h>
  13. #import <objc/List.h>
  14. #import <objc/NXBundle.h>
  15. #import <sys/param.h>
  16. #import <libc.h>
  17.  
  18. #import "Controller.h"
  19. #import "AddressView.h"
  20. #import "Appender.h"
  21.  
  22.  
  23. #define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when connection to database can't be made")
  24. #define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ")
  25. #define CANNOT_ADD NXLocalizedString("Add operation failed", NULL, "Message given to user that add operation has failed")
  26. #define CANNOT_UPDATE NXLocalizedString("Update operation failed",NULL,"Message given to user that update operation has failed")
  27. #define CANNOT_DELETE NXLocalizedString("Delete operation failed",NULL,"Message given to user that delete operation has failed")
  28.  
  29. @implementation Controller
  30.  
  31. - appDidInit:sender
  32. {
  33.         /* Try to connect to the database specified using the Sybase Adaptor
  34.          * and the default login sa, NULL password, SYBASE server, and
  35.          * pubs database.
  36.          */
  37.        database = [[DBDatabase alloc]init];       
  38.     [database connectUsingAdaptor:"SybaseAdaptor"
  39.                                  andString:"sa@SYBASE/pubs"];
  40.  
  41.     if ( ![database isConnected] ) {
  42.             NXRunAlertPanel(FAILURE, CANNOT_CONNECT, "OK", NULL, NULL);
  43.             return self;
  44.             }
  45.         /* Once successfully connected, build the data to be displayed in the
  46.          * matrix
  47.          */
  48.     [self initRecordList];
  49.     [addressView loadCellsFrom:self];
  50.  
  51.         /* Assign the controller to become the database delegate */
  52.     [database setDelegate:self];
  53.  
  54.        cellMatrix = [addressView cellMatrix];
  55.     
  56.          /* Select a cell as a start */
  57.     [[cellMatrix selectCellAt:0 :0] sendAction];
  58.         /* Bring the main application window up front */
  59.     [theWindow makeKeyAndOrderFront:nil];
  60.                 
  61.        return self;
  62. }
  63.  
  64. /* Set up the DBRecordList object. Create a list of properties which contains
  65.  * all properties needed for display or updating.
  66.  */
  67. - initRecordList
  68. {
  69.     id firstName, lastName, phone;
  70.     id state, city, address, zipCode, contract;
  71.     List    *keyList;
  72.     
  73.     if (recordList)
  74.         [recordList free];
  75.     if (propertyList)
  76.         [propertyList free];
  77.  
  78.             /* get the author table from the database */    
  79.     authorEntity = [database entityNamed:"authors"];
  80.     
  81.             /* get the properties  */
  82.     lastName = [authorEntity propertyNamed:"au_lname"];
  83.     firstName = [authorEntity propertyNamed:"au_fname"];
  84.     authId = [authorEntity propertyNamed:"au_id"];
  85.     
  86.      phone = [authorEntity propertyNamed:"phone"];
  87.     address = [authorEntity propertyNamed:"address"];
  88.     city = [authorEntity propertyNamed:"city"];
  89.     state = [authorEntity propertyNamed:"state"];
  90.     zipCode = [authorEntity propertyNamed:"zip"];      
  91.     contract = [authorEntity propertyNamed:"contract"];
  92.     
  93.           /* Set up the property list 
  94.          * Note that certain properties need to be defined in order
  95.          * for an Insert or Update operation to work. This depends
  96.          * on how your data dictionary has been defined. Here pubs
  97.          * is being used as the model.
  98.          */
  99.     propertyList = [[List alloc] init];
  100.     [propertyList addObject:authId];
  101.       [propertyList addObject:lastName];
  102.     [propertyList addObject:firstName];
  103.       [propertyList addObject:phone];
  104.     [propertyList addObject:address];
  105.     [propertyList addObject:city];
  106.     [propertyList addObject:state];
  107.     [propertyList addObject:zipCode];
  108.       [propertyList addObject:contract];
  109.  
  110.        recordList = [[DBRecordList alloc] init];
  111.     
  112.     
  113.         /* A unique key is needed if you want to update or insert new
  114.          * data via the record list into the database. If no key is defined,
  115.          * the data retrieved via the  record list is read-only.
  116.          * This is needed here, since we do not use a dbmodel to define
  117.          * the key.
  118.          */
  119.     keyList = (List *)[[List alloc] init];
  120.     [keyList addObject:authId];
  121.     [recordList setKeyProperties:keyList];
  122.     [keyList free];
  123.     
  124.     /* You must set the properties FIRST before setting the retrieve order */
  125.     [recordList setProperties:propertyList ofSource:authorEntity];
  126.     
  127.     [recordList addRetrieveOrder:DB_AscendingOrder for:lastName];
  128.     [recordList addRetrieveOrder:DB_AscendingOrder for:firstName];                    
  129.     [recordList fetchUsingQualifier:nil];                                 
  130.        recordCount = [recordList count];
  131.     
  132.        return self;
  133. }
  134.     
  135. /* This method is called when selecting "Insert"
  136.  */
  137. - addRecords:sender
  138. {    
  139.     
  140.     int row;
  141.  
  142.     if (recordCount > 0) {
  143.     
  144.         if ( ![addressView addRecordFrom:sender at:(recordCount-1)]) {
  145.             NXRunAlertPanel(NULL, CANNOT_ADD, NULL, NULL, NULL);
  146.             return self;
  147.         }
  148.         
  149.     [self initRecordList];
  150.      [addressView loadCellsFrom:self];
  151.         /* Find the row of the newly inserted record */
  152.     row = [addressView getNewRow];
  153.        [cellMatrix scrollCellToVisible:row :0];
  154.       [[cellMatrix selectCellAt:row:0] sendAction];
  155.       }
  156.       else
  157.           fprintf(stderr, "empty record list - NOP\n");
  158.       return self;
  159. }
  160.  
  161. /* This method gets called when selecting "Update"
  162.  */
  163. - updateRecords:sender
  164. {
  165.     int row;
  166.     
  167.     row = [cellMatrix selectedRow];
  168.     if ( ![addressView updateRecordFrom:sender at:row]) {
  169.         NXRunAlertPanel(NULL, CANNOT_UPDATE, NULL, NULL, NULL);
  170.         return self;
  171.     }
  172.         /* Redisplay the records */
  173.     [self initRecordList];
  174.      [addressView loadCellsFrom:self];
  175.         /* find the row of the updated record */
  176.     row = [addressView getNewRow];
  177.        [cellMatrix scrollCellToVisible:row :0];
  178.       [[cellMatrix selectCellAt:row:0] sendAction];
  179.  
  180.     return self;
  181. }
  182.  
  183.  
  184. - deleteRecords:sender
  185. {    
  186.     
  187.     int row;
  188.     
  189.     row = [cellMatrix selectedRow];
  190.     if (recordCount > 0) {
  191.     
  192.     if (![addressView deleteSelectedRecord:sender]) {
  193.             NXRunAlertPanel(NULL, CANNOT_DELETE, NULL, NULL, NULL);
  194.             return self;
  195.         }
  196.  
  197.     [self initRecordList];
  198.      [addressView loadCellsFrom:self];
  199.        [cellMatrix scrollCellToVisible:row :0];
  200.       [[cellMatrix selectCellAt:row:0] sendAction];
  201.       }
  202.       else
  203.           fprintf(stderr, "empty record list - NOP\n");
  204.     
  205.     return self;
  206. }    
  207. - getRecordList
  208. {
  209.     return recordList;
  210. }
  211.  
  212. - getPropertyList
  213. {
  214.     return propertyList;
  215. }
  216.  
  217. - (int)getRecordCount
  218. {
  219.     return recordCount;
  220. }
  221.  
  222. - showSQLPanel:sender
  223. {
  224.     [SQLPanel makeKeyAndOrderFront:nil];
  225.     return self;
  226. }
  227.  
  228. /* The use of NXBundle here ensures that the proper panel is loaded in case
  229.  * it's being localized.
  230. */
  231. - showInfoPanel:sender
  232. {
  233.     char path[MAXPATHLEN+1];
  234.  
  235.     if (!infoPanel) {
  236.          if ([[NXBundle mainBundle] 
  237.                 getPath:path forResource:"InfoPanel" ofType:"nib"]) {
  238.         infoPanel = [NXApp loadNibFile:path owner:NXApp withNames:NO 
  239.                                                     fromZone:[NXApp zone]];
  240.         }
  241.     }
  242.     [infoPanel orderFront:nil];
  243.     return self;
  244. }
  245.  
  246. - appWillTerminate:sender
  247. {
  248.     /* deallocate what has been allocated */
  249.     if (recordList)
  250.         [recordList free];
  251.     if (propertyList)
  252.         [propertyList free];
  253.     return self;
  254. }
  255.  
  256. /* DBDatabase delegate methods to log error messages and SQL queries */
  257.  
  258. - (BOOL)db:aDb willEvaluateString:(const char*)aString usingBinder:aBinder
  259. {
  260.     [appender appendToText:"SQL Query:\n"];
  261.     [appender appendToText:aString];
  262.     [appender appendToText:"\n"];
  263.     return YES;
  264. }
  265.  
  266. @end
  267.